tf.keras.Model 클래스를 상속해서 이용해서 복잡한 모델을 만들 수 있다.
tf.keras.Model 클래스를 상속한 새로운 클래스를 만들고,
생성자 __init__() 메서드를 정의한다.
__init__ ()에서 self 변수를 통해 참조할 수 있도록 클래스 속성으로 층을 정의하고,
call() 메서드에서 이런 층이 어떻게 정방향 계산에 사용되는지 정의한다.
class MyModel(tf.keras.Model):
def __init__(self):
super(MyModel, self).__init__()
self.hidden_1=tf.keras.layers.Dense(units=4, activation='relu')
self.hidden_2=tf.keras.layers.Dense(units=4, activation='relu')
self.hidden_3=tf.keras.layers.Dense(units=4, activation='relu')
self.output_layer=tf.keras.layers.Dense(units=1, activation='sigmoid')
def call(self, inputs):
h=self.hidden_1(inputs)
h=self.hidden_2(h)
h=self.hidden_3(h)
return self.output_layer(h)
build()
tf.random.set_seed(1)
model=MyModel()
model.build(input_shape=(None, 2))
model.summary()
Model: "my_model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_13 (Dense) multiple 12
_________________________________________________________________
dense_14 (Dense) multiple 20
_________________________________________________________________
dense_15 (Dense) multiple 20
_________________________________________________________________
dense_16 (Dense) multiple 5
=================================================================
Total params: 57
Trainable params: 57
Non-trainable params: 0
_________________________________________________________________
compile() & fit()
model.compile(optimizer=tf.keras.optimizers.SGD(), loss=tf.keras.losses.BinaryCrossentropy(),
metrics=[tf.keras.metrics.BinaryAccuracy()])
hist=model.fit(x_train, y_train, validation_data=(x_valid, y_valid), epochs=200, batch_size=2, verbose=0)
텐서플로 2.2부터 tf.keras.Model 클래스를 상속한 경우 train_step() 메서드에서 tf.GradientTape 컨텍스트로
훈련 단계를 세밀하게 조정할 수 있다.
class MyCustomStepModel(MyModel):
def train_step(self, data):
x, y=data
with tf.GradientTape() as tape:
y_pred=self(x)
loss=self.compiled_loss(y, y_pred, regularization_losses=self.losses)
gradients=tape.gradient(loss, self.trainable_variables)
self.optimizer.apply_gradients(zip(gradients, self.trainable_variables))
self.compiled_metrics.update_state(y, y_pred)
return {m.name: m.result() for m in self.metrics}
train_step 동작
train_step() 메서드의 data 매개변수를 통해 fit() 메서드로 전달된 훈련 데이터가 튜플로 전달된다.
GradientTpae() 컨텍스트 안의 self(x)를 호출하면 Model 객체의 __call__() 메서드가 시행된다.
(__call__() 메서드가 call() 메서드를 호출함을 포함한다.)
손실을 계산하기 위해서 compiled_loss() 메서드를 이용한다.
compiled_loss 메서드를 통해서 지정한 손실을 자동으로 계산해 준다.
compiled_loss()의 regularization_losses 매개변수에 각 층의 규제 손실을 담은 self.losses를 전달하면,
케라스 층의 kernel_regularizer에서 지정한 규제가 자동으로 손실에 반영된다.
tf.GradientTape.gradient를 통해서 그레이디언트를 계산하고, apply_gradients()로 모델 파라미터를 업데이트 한다.
self.trainable_variables를 사용하여 전체 훈련 가능한 변수를 선택
텐서플로 2.4에서는 옵티마이저 클래스가 리팩토링 되어서 사용자 정의 반복에서
옵티마이저의 minimize() 메서드를 직접 호출 가능하다.
->그레이디언트 계산과 업데이트를 하나의 과정으로 간소화
compile() 메서드에서 지정한 측정 지표를 업데이트 하기 위해서 타깃과 예측 값으로 compiled_metrics.update_state()를 호출한다.
train_step은 최종적으로 측정 지표의 이름과 현재 값을 담은 딕셔너리를 반환한다.